package com.ct.application.shipping.service.impl;

import com.ct.application.shipping.model.po.ChuanYuanChuQinSearchPO;
import com.ct.application.shipping.model.vo.ChuanYuanChuQinVO;
import com.ct.application.shipping.service.ChuanYuanChuQinService;
import com.ct.repository.commons.BaseServiceImpl;
import com.ct.shipping.mapper.ChuanYuanChuQinMapper;
import com.ct.shipping.orm.ChuanYuanChuQinDO;
import com.ct.utils.date.DateUtils;
import com.ct.utils.date.TmDateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.ct.utils.date.DateUtils.DATE_PATTERN;

/**
 * <p>
 * 船员出勤 服务实现类
 * </p>
 *
 * @author carlo
 */
@Service
public class ChuanYuanChuQinServiceImpl extends BaseServiceImpl<ChuanYuanChuQinMapper, ChuanYuanChuQinDO>
        implements ChuanYuanChuQinService {

    @Override
    public List<ChuanYuanChuQinVO> findChuanyuanchuqinLists(ChuanYuanChuQinSearchPO searchPO) {
        Date kaiShiRiQi = DateUtils.stringToDate(searchPO.getKaiShiRiQi());
        Date jieShuRiQi = DateUtils.stringToDate(searchPO.getJieShuRiQi());
        List<String> searchMonths = getMonthsBetween(kaiShiRiQi, jieShuRiQi);

        List<ChuanYuanChuQinDO> chuQinList = this.lambdaQuery()
                .eq(StringUtils.isNotEmpty(searchPO.getChuanYuanMing()), ChuanYuanChuQinDO::getChuanYuanMing, searchPO.getChuanYuanMing())
                .eq(!("全选".equals(searchPO.getChuanBoMing())), ChuanYuanChuQinDO::getChuanBoMing, searchPO.getChuanBoMing())
                .eq(!("全选".equals(searchPO.getZhiWei())), ChuanYuanChuQinDO::getZhiWei, searchPO.getZhiWei())
                .list();

        List<ChuanYuanChuQinVO> chuanYuanChuQinVOS = chuQinList.stream()
                .filter(item->{
                    String shangChuanRiQiStr = item.getShangChuanRiQi();
                    Date shangChuanRiQi = TmDateUtil.dateToString(shangChuanRiQiStr,"yyyy-MM-dd");
                    Date currentDate = new Date();
                    if (currentDate.before(shangChuanRiQi)) {   //上船日期在今天之后的 过滤掉
                        return false;
                    }else{
                        return true;
                    }
                })
                .map(item -> {
                        ChuanYuanChuQinVO chuanYuanChuQinVO = new ChuanYuanChuQinVO();
                        BeanUtils.copyProperties(item, chuanYuanChuQinVO);
                        String zhuangTai = item.getZhuangTai(); //状态。在船/下船
                        String shangChuanRiQiStr = item.getShangChuanRiQi();
                        String xiaChuanRiQiStr = item.getXiaChuanRiQi();
                        if (StringUtils.isEmpty(xiaChuanRiQiStr)) {
                            xiaChuanRiQiStr = DateUtils.format(new Date(), DATE_PATTERN);
                        }
                        Date shangChuanRiQi = TmDateUtil.dateToString(shangChuanRiQiStr,"yyyy-MM-dd");
                        Date xiaChuanRiQi =  TmDateUtil.dateToString(xiaChuanRiQiStr,"yyyy-MM-dd");
                        String shangChuanChuQin = item.getShangChuanChuQin();
                        String xiaChuanChuQin = item.getXiaChuanChuQin();
                        if("在船".equals(zhuangTai)){
                            xiaChuanRiQi = new Date();
                            chuanYuanChuQinVO.setShangXiaChuanRiQi(item.getShangChuanRiQi()+"~至今");
                        }else{
                            chuanYuanChuQinVO.setShangXiaChuanRiQi(item.getShangChuanRiQi()+"~"+item.getXiaChuanRiQi());
                        }

                        Map<String, String> monthDays = calculateMonthDays(shangChuanRiQi, xiaChuanRiQi, shangChuanChuQin, xiaChuanChuQin);
                        BigDecimal heJiTianShu = BigDecimal.ZERO;   //合计天数
                        for (String searchMonth : searchMonths) {
                            String value = monthDays.get(searchMonth);
                            if(value != null){
                                heJiTianShu = heJiTianShu.add(new BigDecimal(value));
                            }else{
                                monthDays.put(searchMonth, "0");
                            }
                        }
                        chuanYuanChuQinVO.setHeJiTianShu(heJiTianShu.toString());

                        BigDecimal zaiChuanTianShuBd = BigDecimal.ZERO; //在船天数
                        for (String value : monthDays.values()) {
                            zaiChuanTianShuBd = zaiChuanTianShuBd.add(new BigDecimal(value));
                        }
                        chuanYuanChuQinVO.setZaiChuanTianShu(zaiChuanTianShuBd.toString());
                        chuanYuanChuQinVO.setMonthDays(monthDays);
                        chuanYuanChuQinVO.setSearchMonths(searchMonths);
                        return chuanYuanChuQinVO;
                    }
                ).collect(Collectors.toList());

        return chuanYuanChuQinVOS;
    }

    //计算起始月份和结束月份的每个月份的天数
    private static Map<String, String> calculateMonthDays(Date shangChuanRiQi,Date xiaChuanRiQi,
                                                          String shangChuanChuQin,String xiaChuanChuQin) {
        Map<String, String> monthDays = new TreeMap<>();

        LocalDate shangChuanDate = shangChuanRiQi.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        int sYear = shangChuanDate.getYear();
        int sMonth = shangChuanDate.getMonthValue();
        int sDay = shangChuanDate.getDayOfMonth();

        LocalDate xiaChuanDate = xiaChuanRiQi.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        int xYear = xiaChuanDate.getYear();
        int xMonth = xiaChuanDate.getMonthValue();
        int xDay = xiaChuanDate.getDayOfMonth();

        //上船日期和下船日期是同一月
        if (sYear == xYear && sMonth == xMonth) {
            BigDecimal shangChuanChuQinBd = new BigDecimal(shangChuanChuQin);
            BigDecimal xiaChuanChuQinBd = new BigDecimal(xiaChuanChuQin);
            //如果是同一天
            if (sDay == xDay) {
                monthDays.put(sYear + "-" + (sMonth <= 9 ? "0"+sMonth :sMonth), shangChuanChuQinBd.add(xiaChuanChuQinBd).toString());
                return monthDays;
            } else {
                int tianShu = (xDay - sDay)+1 - 2;
                BigDecimal tianShuBd = new BigDecimal(tianShu);
                monthDays.put(sYear + "-" + (sMonth <= 9 ? "0"+sMonth :sMonth),shangChuanChuQinBd.add(xiaChuanChuQinBd).add(tianShuBd).toString());
                return monthDays;
            }
        }

        LocalDate start = LocalDate.of(sYear, sMonth, sDay);
        LocalDate  end  = LocalDate.of(xYear, xMonth, xDay);
        LocalDate current = start;
        while (!current.isAfter(end)) {
            YearMonth currentMonth = YearMonth.of(current.getYear(), current.getMonth());
            String currentMonthStr = current.getYear()+"-"+(current.getMonthValue() <= 9 ? "0"+current.getMonthValue():current.getMonthValue());
            if (current.equals(start)) {
                int daysInMonth = currentMonth.lengthOfMonth();
                int days = daysInMonth - current.getDayOfMonth() + 1;
                monthDays.put(currentMonthStr, String.valueOf(days));
            } else if (current.getYear() == end.getYear() && current.getMonth() == end.getMonth()) {
                int days = end.getDayOfMonth();
                monthDays.put(currentMonthStr, String.valueOf(days));
            } else {
                int daysInMonth = currentMonth.lengthOfMonth();
                monthDays.put(currentMonthStr, String.valueOf(daysInMonth));
            }
            current = current.plusMonths(1).withDayOfMonth(1);
        }
        //如果是第一天，取上船出勤时间
        String sChuQinDay = monthDays.get(sYear + "-" + (sMonth <= 9 ? "0"+sMonth : sMonth));
        sChuQinDay = new BigDecimal(sChuQinDay).subtract(new BigDecimal("1"))
                .add(new BigDecimal(shangChuanChuQin)).toString();
        monthDays.put(sYear + "-" + (sMonth <= 9 ? "0"+sMonth : sMonth), sChuQinDay);

        //如果是最后一天，取下船出勤时间
        String xChuQinDay = monthDays.get(xYear + "-" + (xMonth <= 9 ? "0"+xMonth : xMonth));
        xChuQinDay = new BigDecimal(xChuQinDay).subtract(new BigDecimal("1"))
                .add(new BigDecimal(xiaChuanChuQin)).toString();
        monthDays.put(xYear + "-" + (xMonth <= 9 ? "0"+xMonth : xMonth), xChuQinDay);
        return monthDays;
    }

    /**
     * 计算两个日期之间的月份集合
     */
    private static List<String> getMonthsBetween(Date startDate, Date endDate) {
        // 将Date对象转换为LocalDate对象
        LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        List<String> months = new ArrayList<>();
        YearMonth startMonth = YearMonth.from(startLocalDate);
        YearMonth endMonth = YearMonth.from(endLocalDate);

        while (!startMonth.isAfter(endMonth)) {
            months.add(String.valueOf(startMonth));
            startMonth = startMonth.plusMonths(1);
        }

        return months;
    }

}
